package org.summer.generator.writer.impl;

import org.summer.generator.StringUtil;
import org.summer.generator.log.Logger;
import org.summer.generator.log.LoggerManager;
import org.summer.generator.vo.MethodInfo;
import org.summer.generator.writer.AbstractJavaFileWriter;

import java.util.List;

/**
 * 数据库操作服务层接口实现类文件写入处理类
 */
public class ServiceImplFileWriter extends AbstractJavaFileWriter {
    private static final Logger log = LoggerManager.getLogger(ServiceImplFileWriter.class);
    @Override
    public void execute() {
        String packageName = project.getServicePackageName();
        String packageDefinition = getPackageDefinition(packageName + ".impl");
        String classDefinition = getClaasImplDefinition(packageName);
        String dependencyClass = getDependencyClass(project.getRepositoryPackageName());
        String serviceObject = StringUtil.firstLetterLowerCase(dependencyClass);
        List<MethodInfo> mds = parseMethodDefinitions(writer.getServiceParentInterface());
        addImport(writer.getRepositoryParentInterface());
        channel.writerNewline(packageDefinition);
        channel.writerEmptyLine();
        channel.writerNewline("import lombok.extern.log4j.Log4j2;");
        channel.writerNewline("import org.springframework.stereotype.Service;");
        channel.writerNewline("import org.summer.common.http.PageBuilder;");
        channel.writerNewline(table.getEntityImportStr());
        channel.writerNewline(IMPORT_LOMBOK_RAC);
        importSet.forEach(channel::writerNewline);
        channel.writerEmptyLine();
        channel.writerNewline(CLASS_REMARK.formatted(table.getRemark() + "服务层操作接口实现类"));
        channel.writerNewline("@Log4j2");
        channel.writerNewline("@Service");
        channel.writerNewline(LOMBOK_RAC);
        channel.writerNewline(classDefinition);
        channel.writerNewline(FIELD_PREFIX + dependencyClass + " " + serviceObject + LINE_END);
        mds.forEach(methodInfo -> writerMethod(methodInfo,dependencyClass,"loadRepository"));
        channel.writerNewline(BLOCK_END);
    }

    @Override
    protected void writerMethod(MethodInfo method, String previousObject, String loadMethodName) {
        channel.writerEmptyLine();
        StringBuilder builder = new StringBuilder(METHOD_PREFIX);
        builder.append(method.getReturnType()).append(SPACING);
        builder.append(method.getMethodName());
        builder.append("(").append(method.getParamTypeAndName()).append(")");
        builder.append(BLOCK_START).append(LINE);
//        builder.append("\t\tlog.debug(\"打印日志\");\n");
        String previousMethodName = getPreviousMethodNamePrintLog(method, builder);
        builder.append(parseReturnBody(method,StringUtil.firstLetterLowerCase(previousObject),previousMethodName));
        builder.append(TAB).append(BLOCK_END);
        channel.writerNewline(builder.toString());
    }

    /**
     * 构建函数返回体内容
     * @param method 方法信息
     * @param previousObject 上一层类对象
     * @param perMethodName 上一层类方法名
     */
    private String parseReturnBody(MethodInfo method, String previousObject,String perMethodName) {
        if (method.getMethodName().contains("Page")){
            return """
                            return PageBuilder.<%s>builder()
                                    .init(page, size)
                                    .total(this::findCount)
                                    .build(this::findLimit);
                    """.formatted(table.getTableUpperName());
        }
        StringBuilder builder = new StringBuilder(METHOD_RETURN_PREFIX);
        builder.append(previousObject).append(".");
        builder.append(perMethodName);
        builder.append("(").append(method.getParamName()).append(");").append(LINE);
        return builder.toString();
    }

    /**
     * 获取调用上一层对象方法名字,打印相关日志
     */
    private String getPreviousMethodNamePrintLog(MethodInfo method, StringBuilder builder) {
        final String mn = method.getMethodName();
        String p_ = "";
        for (int i = 0; i < method.getParameter().size(); i++) {
            if (i > 0){
                p_ += ",";
            }
            p_ += "{}";
        }
        builder.append(LOG_PREFIX);
        if (mn.startsWith(SERVICE_ADD)){
            builder.append(createLog("添加","数据",p_,method.getParamName()));
            return mn.replace(SERVICE_ADD, REPOSITORY_APPEND);
        }
        if (mn.startsWith(SERVICE_FIND)){
            if (mn.contains("Page")){
                builder.append(createLog("查找","分页数据",p_,method.getParamName()));
            }
            if (mn.contains("Id")){
                builder.append(createLog("根据编号查找","数据",p_,method.getParamName()));
            }
            if (mn.contains("List")){
                builder.append("查找").append(table.getRemark()).append("数据列表\");").append(LINE);
            }
            if (mn.contains("Count")){
                builder.append("查找").append(table.getRemark()).append("数据总量\");").append(LINE);
            }
            if (mn.contains("Limit")){
                builder.append(createLog("查找","数据列表(指定区间)",p_,method.getParamName()));
            }
            return mn.replace(SERVICE_FIND, REPOSITORY_SEARCH);
        }
        if (mn.startsWith(SERVICE_REMOVE)){
           if (mn.contains("Id")){
               builder.append(createLog("根据编号删除","数据",p_,method.getParamName()));
           }
            return mn.replace(SERVICE_REMOVE, REPOSITORY_CANCEL);
        }
        if (mn.startsWith(SERVICE_MODIFY)){
            builder.append(createLog("修改","数据",p_,method.getParamName()));
            return mn.replace(SERVICE_MODIFY, REPOSITORY_EDIT);
        }
        return mn;
    }

    /**
     * 构建日志
     */
    private String createLog(String prefix,String suffix,String paramsPlaceholder,String params){
            return prefix +
                    table.getRemark() +
                    suffix + ": " +
                    paramsPlaceholder + "\""
                    + "," + params + ");"
                    + LINE;
    }
}
